package com.pms.utils;

import com.alibaba.fastjson.JSONObject;
import com.baidubce.BceClientException;
import com.baidubce.internal.RestartableInputStream;
import com.baidubce.util.DateUtils;
import com.baidubce.util.JsonUtils;
import com.pms.exception.RRException;
import com.pms.util.baidu.AuthorizationUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * 百度物接入请求工具类
 * com.alibaba.fastjson.JSONObject.parseObject 将null 装换为 null对象
 * net.sf.json.JSONObject.fromObject 将null装换为 "null"字符串
 */
@Component
public class IotAccessHttpClientUtil {
    private Logger logger = LoggerFactory.getLogger(IotAccessHttpClientUtil.class);
    @Autowired
    AuthorizationUtil authorizationUtil;
    @Value("${baidu.iot_access_bj.endpointName}")
    private String bjEndpointName;
    @Value("${baidu.iot_access_gz.endpointName}")
    private String gzEndpointName;
    @Value("${baidu.iot_access_bj.principalName}")
    private String bjPrincipalName;
    @Value("${baidu.iot_access_gz.principalName}")
    private String gzPrincipalName;
    public String readDefaultBjEndpointName(){
        return bjEndpointName==null ? "":bjEndpointName;
    }

    /**
     * @param address 1-广州,2-北京(默认)
     * @return
     */
    public String readDefaultEndpointName(Integer address){
        if(address!=null&&address==1){
            return gzEndpointName==null ? "":gzEndpointName;
        }
        return bjEndpointName==null ? "":bjEndpointName;
    }
    /**
     * @param address 1-广州,2-北京(默认)
     * @return
     */
    public String readDefaultPrincipalName(Integer address){
        if(address!=null&&address==1){
            return gzPrincipalName==null ? "":gzPrincipalName;
        }
        return bjPrincipalName==null ? "":bjPrincipalName;
    }
    /*===================物管理============*/
/* 广州地址 api支持*/
    private static final String DEFAULT_HTTPURL_GZ = "http://iot.gz.baidubce.com";
    private static final String DEFAULT_HOST_GZ = "iot.gz.baidubce.com";
/* 北京地址 api暂不支持*/
    private static final String DEFAULT_HTTPURL_BJ = "http://iot.bj.baidubce.com";
    private static final String DEFAULT_HOST_BJ = "iot.bj.baidubce.com";

//    public static void main(String arg[]) throws Exception {
////        String str ="0110110";
////        int lastIndex= str.lastIndexOf("1");
////        int index= str.indexOf("1");
////       while (index<lastIndex){
////           index = str.indexOf("1",index+1);
////           System.out.print(index); System.out.print(",");
////       }
//        String ruleJsonStr ="{\"SBZT\":{\"way\":\"hexadecimal\",\"val\":\"2\",\"isReversal\":\"1\",\"readWay\":\"index\",\"readVal\":\"1\",\"indexJson\":{\"0\":\"0\",\"1\":\"1\",\"2\":\"0\",\"3\":\"1\",\"4\":\"0\",\"5\":\"1\",\"6\":\"0\",\"7\":\"1\",\"8\":\"0\",\"9\":\"1\",\"10\":\"0\",\"11\":\"1\",\"12\":\"0\",\"13\":\"1\",\"14\":\"2\",\"15\":\"3\",}},\"GZZT\":{\"way\":\"hexadecimal\",\"val\":\"2\",\"isReversal\":\"1\",\"readWay\":\"index\",\"readVal\":\"1\",}}";JSONObject ruleJson =null;
//        ruleJson = JSONObject.parseObject(ruleJsonStr);
//        System.out.print(ruleJson);
//    }

    /*=============POST请求  address-请求地址 1-广州(默认),2-北京======================*/
    public JSONObject iotDoPost_POST(String url, JSONObject paramJson) {
        if(paramJson == null){
            throw new RRException("post请求,paramJson不能为空",400);
        }
        return iotDoPost("POST", url, paramJson);
    }
    public JSONObject iotDoPost_POST(String url, JSONObject paramJson,Integer address) {
        if(paramJson == null){
            throw new RRException("post请求,paramJson不能为空",400);
        }
        return iotDoPost("POST", url, paramJson,address);
    }
    /*=============GET请求  address-请求地址 1-广州(默认),2-北京======================*/
    public JSONObject iotDoPost_GET(String url, JSONObject paramJson) {
        return iotDoPost("GET", url, paramJson);
    }
    public JSONObject iotDoPost_GET(String url, JSONObject paramJson,Integer address) {
        return iotDoPost("GET", url, paramJson,address);
    }
    /*=============PUT请求 address-请求地址 1-广州(默认),2-北京======================*/
    public JSONObject iotDoPost_PUT(String url, JSONObject paramJson) {
        if(paramJson == null){
            throw new RRException("put请求,paramJson不能为空",400);
        }
        return iotDoPost("PUT", url, paramJson);
    }
    public JSONObject iotDoPost_PUT(String url, JSONObject paramJson,Integer address) {
        if(paramJson == null){
            throw new RRException("put请求,paramJson不能为空",400);
        }
        return iotDoPost("PUT", url, paramJson,address);
    }
    /*=============DELETE请求 address-请求地址 1-广州(默认),2-北京======================*/
    public JSONObject iotDoPost_DELETE(String url, JSONObject paramJson) {
        return iotDoPost("DELETE", url, paramJson);
    }
    public JSONObject iotDoPost_DELETE(String url, JSONObject paramJson,Integer address) {
        return iotDoPost("DELETE", url, paramJson,address);
    }
    /**
     *
     * @param reqMethod
     * @param url
     * @param paramJson
     * @param address 地址 1-广州,2-北京(默认)
     * @return
     */
    public JSONObject iotDoPost(String reqMethod, String url, JSONObject paramJson,Integer address) {
        if(address==null||address==2){
            return iotDoPost_BJ(reqMethod,url,paramJson);
        }
        if(address==1){
            return iotDoPost_GZ(reqMethod,url,paramJson);
        }else{
            return iotDoPost_BJ(reqMethod,url,paramJson);
        }
    }

    /**
     * 默认指向广州
     * @param reqMethod
     * @param url
     * @param paramJson
     * @return
     */
    public JSONObject iotDoPost(String reqMethod, String url, JSONObject paramJson) {
        return iotDoPost_GZ(reqMethod,url,paramJson);
    }

    public JSONObject iotDoPost_GZ(String reqMethod, String url, JSONObject paramJson) {
        return iotDoPost(reqMethod,url,paramJson,getDefaultHttpUrl_GZ(),getDefaultHttpHost_GZ());
    }
    public JSONObject iotDoPost_BJ(String reqMethod, String url, JSONObject paramJson) {
        return iotDoPost(reqMethod,url,paramJson,getDefaultHttpUrl_BJ(),getDefaultHttpHost_BJ());
    }
    /**
     * http-->>post请求
     * @return
     */
    public JSONObject iotDoPost(String reqMethod, String url, JSONObject paramJson,String urlPrefix,String host) {
        DefaultHttpClient client = new DefaultHttpClient();
        HttpRequestBase req = null;
        HttpParams paramsObj = null;
        if(!url.startsWith(urlPrefix)){// 如果不是 DEFAULT_HTTPURL 开头的
            url = urlPrefix+url;
        }
        if (reqMethod == null) {
            reqMethod = "GET";
        }
        if (reqMethod.equals("GET")) {
            url = url + generate_ReqParamStr(paramJson);
            req = new HttpGet(url);
        }
        if (reqMethod.equals("DELETE")) {
            url = url + generate_ReqParamStr(paramJson);
            req = new HttpDelete(url);
        }
        if (reqMethod.equals("POST")) {
            HttpPost reqt = new HttpPost(url);
            if (paramJson != null && !paramJson.isEmpty()) {
                byte[] content = toJson(paramJson);
                reqt.setEntity(new InputStreamEntity(RestartableInputStream.wrap(content), Long.parseLong(Integer.toString(content.length))));
            } else {
                try {
                    StringEntity s = new StringEntity("");
                    s.setContentEncoding("UTF-8");
                    s.setContentType("application/json");
                    reqt.setEntity(s);
                } catch (UnsupportedEncodingException ex) {
                    ex.printStackTrace();
                }
            }
            req = reqt;
        }
        if (reqMethod.equals("PUT")) {
            HttpPut reqt = new HttpPut(url);
            if (paramJson != null && !paramJson.isEmpty()) {
                byte[] content = toJson(paramJson);
                reqt.setEntity(new InputStreamEntity(RestartableInputStream.wrap(content), Long.parseLong(Integer.toString(content.length))));
            } else {
                try {
                    StringEntity s = new StringEntity("");
                    s.setContentEncoding("UTF-8");
                    s.setContentType("application/json");
                    reqt.setEntity(s);
                } catch (UnsupportedEncodingException ex) {
                    ex.printStackTrace();
                }
            }
            req = reqt;
        }
        req.addHeader("Host", host);
        req.addHeader("Content-Type", "application/json; charset=utf-8");
//        req.addHeader("Content-Type", " text/plain;charset=UTF-8");

        req.addHeader("x-bce-date", DateUtils.formatAlternateIso8601Date(new Date()));
        Map<String, String> paramToSignMap = createParamToSignMap(url);//获取签名所需的参数
        req.addHeader("Authorization", authorizationUtil.generate_Authorization(req, paramToSignMap));
        JSONObject response = null;
        try {
            Long startTime = System.currentTimeMillis();
            HttpResponse res = client.execute(req);
            HttpEntity entity = res.getEntity();
            if(entity!=null){
                String result = EntityUtils.toString(entity);// 返回json格式：
                if (res.getStatusLine().getStatusCode() == 400) {
                    logger.info("错误信息=======");
                    logger.info(result);
                }
                if (res.getStatusLine().getStatusCode() == 403) {
                    throw new RRException("Access Key ID错误", 400);
                }
                if (res.getStatusLine().getStatusCode() == 500) {
                    throw new RRException("百度内部服务发生错误", 400);
                }
                response = JSONObject.parseObject(result);
            }
            if(response == null){response = new JSONObject();}
            if(res.getStatusLine().getStatusCode() == 200){
                response.put("iotHttpCode",200);
            }else{
                response.put("iotHttpCode",400);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return response;
    }

    //设置请求参数
    private static void setPostData(HttpPost httpPost, Map<String, String> params) {
        /*另外一种设置请求参数方法*/
        List<NameValuePair> list = new ArrayList<NameValuePair>();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }
        HttpEntity httpEntity = null;
        try {
            httpEntity = new UrlEncodedFormEntity(list, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        httpPost.setEntity(httpEntity);//设置请求主体
    }

    public Map<String, String> createParamToSignMap(String url) {
        Map<String, String> paramToSignMap = new HashMap<String, String>();
        int paramStatIndex = url.indexOf("?");
        if (paramStatIndex > 0) {
            //获取问号中的参数
            String paramStr = url.substring(paramStatIndex + 1, url.length());
            String[] paramArr = paramStr.split("&");
            for (int x = 0; x < paramArr.length; x++) {
                String[] paramXArr = paramArr[x].split("=");
                if (paramXArr.length == 1) {
                    paramToSignMap.put(paramXArr[0], null);
                }
                if (paramXArr.length == 2) {
                    paramToSignMap.put(paramXArr[0], paramXArr[1]);
                }
                if (paramXArr.length > 2) {
                    throw new RRException("请求路径出错:" + url);
                }
            }
        }
        return paramToSignMap;
    }


    protected byte[] toJson(Object bceRequest) {
        String jsonStr = JsonUtils.toJsonString(bceRequest);

        try {
            return jsonStr.getBytes("UTF-8");
        } catch (UnsupportedEncodingException var4) {
            throw new BceClientException("Fail to get UTF-8 bytes", var4);
        }
    }

    public String generate_ReqParamStr(JSONObject paramJson) {
        StringBuilder ReqParamStr = new StringBuilder("");
        if (paramJson != null) {
            Map<String, Object> paramMap = paramJson;
            boolean tag = false;
            for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
                if (entry.getValue() != null) {
                    if (tag) {
                        ReqParamStr.append("&").append(entry.getKey()).append("=").append(entry.getValue());
                    }
                    if (!tag) {
                        ReqParamStr.append("?").append(entry.getKey()).append("=").append(entry.getValue());
                        tag =true;
                    }
                }
            }
        }
        return ReqParamStr.toString();
    }

    public String generate_ReqParamStr(Map<String, Object> paramMap) {
        StringBuilder ReqParamStr = new StringBuilder("");
        if (paramMap != null) {
            boolean tag = false;
            for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
                if (entry.getValue() != null) {
                    if (tag) {
                        ReqParamStr.append("&").append(entry.getKey()).append("=").append(entry.getValue());
                    }
                    if (!tag) {
                        ReqParamStr.append("?").append(entry.getKey()).append("=").append(entry.getValue());
                        tag =true;
                    }
                }
            }
        }
        return ReqParamStr.toString();
    }

    public static String getDefaultHttpUrl_GZ() {
        return DEFAULT_HTTPURL_GZ;
    }
    public static String getDefaultHttpUrl_BJ() {
        return DEFAULT_HTTPURL_BJ;
    }
    public static String getDefaultHttpHost_GZ() {
        return DEFAULT_HOST_GZ;
    }
    public static String getDefaultHttpHost_BJ() {
        return DEFAULT_HOST_BJ;
    }
}